//! 资源上下文
//!
//! 定义资源的多维度上下文，用于标识和定位资源

use super::hierarchy::ResourceHierarchy;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// 资源上下文
///
/// 包含资源的层级结构和多维度信息
///
/// # 示例
///
/// ```ignore
/// use common::resource::{ResourceContext, ResourceHierarchy, dimension_keys};
///
/// let hierarchy = ResourceHierarchy::three_level(
///     "610000", "陕西省",
///     "610100", "西安市",
///     "610102", "新城区"
/// );
///
/// let mut context = ResourceContext::new(hierarchy);
/// context.set_dimension(dimension_keys::YEAR, "2022");
/// context.set_dimension(dimension_keys::VERSION, "v2.0");
///
/// // 资源键: "610102_version_v2.0_year_2022"
/// let key = context.resource_key(context.current_code());
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceContext {
    /// 层级结构
    pub hierarchy: ResourceHierarchy,

    /// 资源维度（key-value 形式存储所有维度）
    pub dimensions: HashMap<String, String>,

    /// 项目ID（可选）
    pub project_id: Option<String>,
}

impl ResourceContext {
    /// 创建新的资源上下文
    pub fn new(hierarchy: ResourceHierarchy) -> Self {
        Self { hierarchy, dimensions: HashMap::new(), project_id: None }
    }

    /// 创建带年份的资源上下文（便捷方法）
    pub fn with_year(
        hierarchy: ResourceHierarchy,
        year: impl Into<String>,
    ) -> Self {
        let mut context = Self::new(hierarchy);
        context.set_dimension(super::dimension_keys::dimension_keys::YEAR, year);
        context
    }

    /// 设置维度
    ///
    /// 支持链式调用
    pub fn set_dimension(
        &mut self,
        key: impl Into<String>,
        value: impl Into<String>,
    ) -> &mut Self {
        self.dimensions.insert(key.into(), value.into());
        self
    }

    /// 获取维度值
    pub fn get_dimension(
        &self,
        key: &str,
    ) -> Option<&String> {
        self.dimensions.get(key)
    }

    /// 获取年份（便捷方法）
    pub fn year(&self) -> Option<&String> {
        self.get_dimension(super::dimension_keys::dimension_keys::YEAR)
    }

    /// 设置项目ID
    pub fn with_project_id(
        mut self,
        project_id: impl Into<String>,
    ) -> Self {
        self.project_id = Some(project_id.into());
        self
    }

    /// 获取当前层级代码
    pub fn current_code(&self) -> &str {
        self.hierarchy.current_code()
    }

    /// 获取当前层级名称
    pub fn current_name(&self) -> &str {
        self.hierarchy.current_name()
    }

    /// 生成资源标识符
    ///
    /// 格式: `{code}_{dim1}_{val1}_{dim2}_{val2}_...`
    /// 维度按键名字母顺序排序
    ///
    /// # 示例
    ///
    /// ```ignore
    /// // dimensions: {year: "2022", version: "v2.0"}
    /// // 结果: "610100_version_v2.0_year_2022"
    /// ```
    pub fn resource_key(
        &self,
        code: &str,
    ) -> String {
        if self.dimensions.is_empty() {
            return code.to_string();
        }

        let mut sorted_dims: Vec<_> = self.dimensions.iter().collect();
        sorted_dims.sort_by_key(|(k, _)| *k);

        let mut key = code.to_string();
        for (k, v) in sorted_dims {
            key.push('_');
            key.push_str(k);
            key.push('_');
            key.push_str(v);
        }

        key
    }

    /// 获取回退顺序的资源键列表
    pub fn fallback_keys(&self) -> Vec<String> {
        self.hierarchy.fallback_order().into_iter().map(|code| self.resource_key(&code)).collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::resource::dimension_keys::dimension_keys;

    #[test]
    fn test_resource_key_no_dimensions() {
        let hierarchy = ResourceHierarchy::single_level("610000", "陕西省");
        let context = ResourceContext::new(hierarchy);

        assert_eq!(context.resource_key("610000"), "610000");
    }

    #[test]
    fn test_resource_key_with_dimensions() {
        let hierarchy = ResourceHierarchy::single_level("610100", "西安市");
        let mut context = ResourceContext::new(hierarchy);

        context.set_dimension(dimension_keys::YEAR, "2022");
        context.set_dimension(dimension_keys::VERSION, "v2.0");

        // 维度按字母顺序排序: version, year
        assert_eq!(context.resource_key("610100"), "610100_version_v2.0_year_2022");
    }

    #[test]
    fn test_fallback_keys() {
        let hierarchy = ResourceHierarchy::three_level("610000", "陕西省", "610100", "西安市", "610102", "新城区");

        let mut context = ResourceContext::new(hierarchy);
        context.set_dimension(dimension_keys::YEAR, "2022");

        let keys = context.fallback_keys();
        assert_eq!(keys.len(), 3);
        assert_eq!(keys[0], "610102_year_2022");
        assert_eq!(keys[1], "610100_year_2022");
        assert_eq!(keys[2], "610000_year_2022");
    }
}
